﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Legend.Component.Interface;
using Legend.Component;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

namespace Legend.Object
{
    public sealed class GameObject
    {
        private ComponentManager components = new ComponentManager();
        private Queue<IComponent> createdComponent = null;
        private Queue<Type> deletedComponent = null;
        private bool updating = false;
        public GameObject()
        {

        }

        public T CreateComponent<T>() where T : class, IComponent, new()
        {
            T component = new T();

            component.Owner = this;

            if (updating)
            {
                if (createdComponent == null)
                {
                    createdComponent = new Queue<IComponent>();
                    createdComponent.Enqueue(component);
                }
            }
            else
            {
                if (!components.RegistComponent(component))
                {
                    throw new InvalidOperationException("same type component could not be registed in same component manager");
                }
            }
            
            return component;
        }

        public void RemoveComponent<T>() where T : class, IComponent
        {
            if (updating)
            {
                if (deletedComponent == null)
                {
                    deletedComponent = new Queue<Type>();
                }
                deletedComponent.Enqueue(typeof(T));
            }
            else
            {
                components.UnRegistComponent<T>();
            }
        }

        public T FindComponent<T>() where T : class, IComponent
        {
            return components.FindComponent<T>();
        }

        public void Update(GameTime gameTime, ContentManager contentManager)
        {
            updating = true;
            foreach (IComponent component in components.GetComponents())
            {
                IUpdatable updatable = component as IUpdatable;
                if (updatable != null)
                {
                    updatable.Update(gameTime, contentManager);
                }
            }

            if (createdComponent != null)
            {
                while (createdComponent.Count > 0)
                {
                    if (!components.RegistComponent(createdComponent.Dequeue()))
                    {
                        throw new InvalidOperationException("same type component could not be registed in same component manager");
                    }
                }
                createdComponent = null;
            }

            if (deletedComponent != null)
            {
                while (deletedComponent.Count > 0)
                {
                    components.UnRegistComponent(deletedComponent.Dequeue());
                }
                deletedComponent = null;
            }
            updating = false;
        }

        //public void Draw(GraphicsDevice device)
        //{
        //    foreach (IComponent component in components.GetComponents())
        //    {
        //        IRenderable renderable = component as IRenderable;
        //        if (renderable != null)
        //        {
        //            renderable.Render(device);
        //        }
        //    }
        //}
    }
}
